package com.darwin.darwinGpuEngine.core.materials {

    import flash.display.BitmapData;
    import flash.geom.Point;
    import flash.geom.Rectangle;
    import flash.utils.Dictionary;

    public class ASpriteSheetBase {

        protected var frames:Vector.<Rectangle> = new Vector.<Rectangle>();
        protected var offsets:Vector.<Point> = new Vector.<Point>();
        protected var sourceSizes:Vector.<Point> = new Vector.<Point>();
        protected var frameNameToIndex:Dictionary = new Dictionary();
        protected var uvRects:Vector.<Rectangle>;
        protected var spritesPackedWithoutSpace:Boolean;

        protected var ctime:Number = 0.0;
        protected var otime:Number = 0.0;
        protected var interp:Number = 0.0;

        protected var frameIdx:uint = 0;

        protected var activeAnimation:SpriteSheetAnimation;
        protected var animationMap:Dictionary = new Dictionary();

        public var frameUpdated:Boolean = true;

        protected var fps:uint;

        protected var _spriteWidth:Number;
        protected var _spriteHeight:Number;
        protected var _sheetWidth:Number;
        protected var _sheetHeight:Number;

        public function get spriteWidth():Number {
            return _spriteWidth;
        }

        public function get spriteHeight():Number {
            return _spriteHeight;
        }

        protected var _frame:uint = 0;

        public function get frame():uint {
            return _frame;
        }

        public function set frame(value:uint):void {
            if(frame != value) {
                _frame = value;
                frameUpdated = true;

                if(frames.length - 1 >= _frame) {
                    _spriteWidth = frames[_frame].width;
                    _spriteHeight = frames[_frame].height;
                }
            }
        }

        public function ASpriteSheetBase() {
        }

        public function update(t:Number):void {

            if(!activeAnimation) return;

            ctime = t;

            interp += fps * (ctime - otime);
            if(interp >= 1.0) {
                frameIdx++;
                interp = 0;
            }

            if(activeAnimation.loop) {
                frameIdx = frameIdx % activeAnimation.numFrames;
            } else {
                frameIdx = Math.min(frameIdx, activeAnimation.numFrames - 1);
            }

            frame = activeAnimation.frames[frameIdx];

            otime = ctime;
        }

        public function addAnimation(name:String, keyFrames:Array, loop:Boolean, keyIsString:Boolean = false):void {
            animationMap[name] = new SpriteSheetAnimation(keyFrames, loop);
        }

        public function playAnimation(name:String, startIdx:uint = 0, restart:Boolean = false):void {
            if(restart || activeAnimation != animationMap[name]) {
                frameIdx = startIdx;
                activeAnimation = animationMap[name];
            }
        }

        public function clone():ASpriteSheetBase {
            return null;
        }

        public function getOffsetForFrame():Point {
            return offsets[frame];
        }

        public function getUVRectForFrame(textureWidth:Number, textureHeight:Number):Rectangle {

            if(uvRects[frame]) {
                return uvRects[frame];
            }

            var rect:Rectangle = frames[frame].clone();
            var texturePixelOffset:Point = new Point((textureWidth - _sheetWidth) / 2.0, (textureHeight - _sheetHeight) / 2.0);

            rect.x += texturePixelOffset.x;
            rect.y += texturePixelOffset.y;

            if(spritesPackedWithoutSpace) {
                rect.x += 0.5;
                rect.y += 0.5;

                rect.width -= 1.0;
                rect.height -= 1.0;
            }

            rect.x /= textureWidth;
            rect.y /= textureHeight;
            rect.width /= textureWidth;
            rect.height /= textureHeight;

            uvRects[frame] = rect;

            return rect;
        }
    }
}
